package com.heima.wemedia.service.impl;

import com.alibaba.druid.sql.visitor.functions.If;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.heima.common.dtos.PageResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.threadlocal.UserThreadLocalUtils;
import com.heima.common.util.BeanHelper;
import com.heima.common.util.JsonUtils;
import com.heima.model.media.dtos.WmNewsDto;
import com.heima.model.media.dtos.WmNewsPageReqDto;
import com.heima.model.media.dtos.WmNewsResultDTO;
import com.heima.wemedia.entity.WmMaterial;
import com.heima.wemedia.entity.WmNews;
import com.heima.wemedia.entity.WmNewsMaterial;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.WmMaterialService;
import com.heima.wemedia.service.WmNewsAuditService;
import com.heima.wemedia.service.WmNewsMaterialService;
import com.heima.wemedia.service.WmNewsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.xml.bind.v2.model.core.ID;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.heima.common.constants.message.WmNewsUpDownConstants.WM_NEWS_UP_OR_DOWN_TOPIC;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author LX
 * @since 2022-06-20
 */
@Slf4j
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsAuditService auditService;
    @Autowired
    private KafkaTemplate kafkaTemplate;

    /**
     * @param dto
     * @return
     */
    @Override
    public PageResult<WmNewsResultDTO> findByPage(WmNewsPageReqDto dto) {
        Integer userId = UserThreadLocalUtils.getUserId();
        Page<WmNews> page = new Page<>(dto.getPage(), dto.getSize());

        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmNews::getWmUserId, userId)
                .eq(dto.getChannelId() != null, WmNews::getChannelId, dto.getChannelId()).
                like(StringUtils.isNoneBlank(dto.getKeyword()), WmNews::getTitle, dto.getKeyword()).
                gt(dto.getBeginPubDate() != null, WmNews::getPublishTime, dto.getBeginPubDate()).
                lt(dto.getEndPubDate() != null, WmNews::getPublishTime, dto.getEndPubDate());

        if (dto.getStatus() != null && dto.getStatus() != -1) {
            if (dto.getStatus() == 1) {
                //参数1待审核  对应数据库
                //where status in (1,3)
                queryWrapper.in(WmNews::getStatus, new Integer[]{1, 3});
            } else if (dto.getStatus() == 4) {
                queryWrapper.in(WmNews::getStatus, new Integer[]{4, 8, 9});
            } else {
                queryWrapper.eq(WmNews::getStatus, dto.getStatus());
            }
        }
        IPage<WmNews> wmNewsIPage = page(page, queryWrapper);
        if (wmNewsIPage == null || CollectionUtils.isEmpty(wmNewsIPage.getRecords())) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        List<WmNewsResultDTO> resultDTOList = BeanHelper.copyWithCollection(wmNewsIPage.getRecords(), WmNewsResultDTO.class);
        return new PageResult<>(dto.getPage(), dto.getSize(), wmNewsIPage.getTotal(), resultDTOList);
    }

    @Autowired
    private WmNewsMaterialService wmNewsMaterialService;

    /**
     * 新增或修改保存提交审核
     *
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submit(WmNewsDto dto) {
        //获取登录用户
        Integer userId = UserThreadLocalUtils.getUserId();
        //对象转化dto->entity
        WmNews wmNews = BeanHelper.copyProperties(dto, WmNews.class);
        //如果是新增文章,添加创建时间
        if (dto.getId() == null) {
            wmNews.setCreatedTime(new Date());
            wmNews.setEnable(true);
        }
        wmNews.setWmUserId(userId);
        //如果是提交审核,添加提交审核时间
        if (dto.getStatus() == 1) {
            wmNews.setSubmitedTime(new Date());

        }
        //如果有封面数据,需要把dto的list->entity String
        if (!CollectionUtils.isEmpty(dto.getImages())) {
            String imagesStr = dto.getImages().stream().collect(Collectors.joining(","));
            wmNews.setImages(imagesStr);
        }
        //新增\修改\文章数据
        boolean b = saveOrUpdate(wmNews);
        if (!b) {
            log.error("新增、修改、提交文章出错");
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
        //新增\修改\文章素材中间表数据
        Integer wmNewsId = wmNews.getId();
        // 获取文章的素材  在文章的正文和封面会使用素材
        if (dto.getId() != null) {
            //修改、提交文章数据，需要根据文章的id把中间表的数据先删除
            wmNewsMaterialService.removeByWmNewsId(wmNewsId);
        }
        //获取文章 的content使用 的素材信息
        List<Integer> contentMaterialIds = getMaterialIdsFromeContent(wmNews.getContent());
        //保存文章素材中间表数据
        if (!CollectionUtils.isEmpty(contentMaterialIds)) {

            wmNewsMaterialService.saveBatchNewsAndMaterialids(wmNewsId, contentMaterialIds, 0);
        }

        //获取文章的封面images使用的素材信息
        if (!CollectionUtils.isEmpty(dto.getImages())) {
            List<Integer> imagesMaterialIds = getMaterialIdFromImages(dto.getImages());
            if (!CollectionUtils.isEmpty(imagesMaterialIds)) {
                //保存文章素材中间表数据
                wmNewsMaterialService.saveBatchNewsAndMaterialids(wmNewsId, imagesMaterialIds, 1);
            }
        }

        //如果提交审核,就调用审核的代码
        if (dto.getStatus() == 1) {
            auditService.auditWmNews(wmNews);
        }

    }

    /**
     * 根据主键id查询文章
     *
     * @param wmNewsId
     * @return
     */
    @Override
    public WmNewsResultDTO getNewsById(Integer wmNewsId) {
        Integer userId = UserThreadLocalUtils.getUserId();
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmNews::getWmUserId, userId).eq(WmNews::getId, wmNewsId);
        WmNews wmNews = getOne(queryWrapper);
        if (wmNews == null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        return BeanHelper.copyProperties(wmNews, WmNewsResultDTO.class);
    }

    /**
     * 卡夫卡的上下架
     * @param dto
     */
    @Override
    public void downOrUp(WmNewsDto dto) {
        Integer userId = UserThreadLocalUtils.getUserId();
        if(userId == null || userId==0){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNews::getId,dto.getId()).eq(WmNews::getWmUserId,userId);
        WmNews wmNews = getOne(queryWrapper);
        if(wmNews == null){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        if(wmNews.getStatus() !=9){
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID);
        }
        if(dto.getEnable().equals(wmNews.getEnable())){
//          前端传递的上下架和数据库里的一致就什么都不用做
            return ;
        }
//        更新自媒体文章 上下架状态
        UpdateWrapper<WmNews> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .eq(WmNews::getId,dto.getId())
                .set(WmNews::getEnable,dto.getEnable());
        update(updateWrapper);

//        构造消息内容
//        map  key  - articleId    key - enable value - 1 :上架  0：下架
        Map<String,Long> map = new HashMap<>();
        map.put("articleId",dto.getArticleId());
        map.put("enable",dto.getEnable()?1L:0L);
//        成功后发送kafka消息
        kafkaTemplate.send(WM_NEWS_UP_OR_DOWN_TOPIC,JsonUtils.toString(map));
    }

    @Autowired
    private WmMaterialService wmMaterialService;

    /**
     * 根据前段传递的 图片路径
     *
     * @param images
     * @return
     */
    private List<Integer> getMaterialIdFromImages(List<String> images) {
        LambdaQueryWrapper<WmMaterial> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.in(WmMaterial::getUrl, images);
        List<WmMaterial> wmMaterialList = wmMaterialService.list();
        //获取素材id集合
        List<Integer> ids = wmMaterialList.stream().map(WmMaterial::getId).collect(Collectors.toList());

        return ids;
    }

    /**
     * 获取文章内容中的素材id
     *
     * @param content
     * @return
     */
    private List<Integer> getMaterialIdsFromeContent(String content) {
        if (StringUtils.isBlank(content)) {
            return null;
        }
        List<Integer> ids = new ArrayList<>();
        List<Map<String, Object>> list = JsonUtils.nativeRead(content, new TypeReference<List<Map<String, Object>>>() {
        });
        for (Map<String, Object> map : list) {
            String type = map.get("type").toString();
            if ("imag".equals(type)) {
                Integer materialId = Integer.valueOf(map.get("id").toString());
                ids.add(materialId);
            }
        }
        return ids;
    }


}
